package biolabs.mcl

import biolabs.core.Application
import biolabs.mcl.syntax._

object DelegateCombination {
	def analyze(ast: DelegateCombinationAST, model: ModelDefinition, interaction: ActualType, app: Application): AnalysisResult[DelegateCombination] = {

		// analyze providers of source delegates
		val sources = {
			val (suc, err) = ast.sourceDelegates map { DelegateDesignation.analyze(_, interaction, model, app) } partition { _.successful }
			if(!err.isEmpty)
				return AnalysisError(err map { _.getErrorMessage() } mkString "\n")
			suc map { _.getResult() }
		}

		ast match {
			case SimpleDelegateCombinationAST(_) => AnalysisSuccess(SimpleDelegateCombination(interaction, sources.head))
			case MultiDelegateCombinationAST(_, combinator) => AnalysisSuccess(MultiDelegateCombination(interaction, sources, combinator))
		}
	}
}

/** Instructs how to combine a series of interaction delegates into one. */
abstract class DelegateCombination {
	val interaction: ActualType
}

/** A trivial combination consisting of one interaction delegate. */
case class SimpleDelegateCombination(
		override val interaction: ActualType,
		val delegate: DelegateDesignation)
extends DelegateCombination

/** A combination of multiple interaction delegates. */
case class MultiDelegateCombination(
		override val interaction: ActualType,
		val delegates: Iterable[DelegateDesignation],
		val combinator: String)
extends DelegateCombination